package com.jinyi.wwdeng.autodialer.manager

import android.content.Context
import android.util.Log
import com.jinyi.wwdeng.autodialer.data.CallTask
import com.jinyi.wwdeng.autodialer.http.HttpApi
import com.jinyi.wwdeng.autodialer.http.HttpUtil
import com.jinyi.wwdeng.autodialer.repository.CallTaskRepository
import com.jinyi.wwdeng.autodialer.utils.AppConfig
import com.jinyi.wwdeng.autodialer.utils.AppException
import com.jinyi.wwdeng.autodialer.utils.ServiceConfig
import com.jinyi.wwdeng.autodialer.utils.event.EventAction
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.ACTION_UPDATE_TOAST
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.ACTION_UPDATE_UPLOAD
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.EXTRA_MESSAGE
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.EXTRA_PHONE_NUMBER
import com.jinyi.wwdeng.autodialer.utils.event.EventAction.EXTRA_STATUS
import kotlinx.coroutines.delay
import java.io.File
import java.util.concurrent.ConcurrentHashMap
import kotlin.time.Duration.Companion.seconds

/**
 * 文件上传管理器
 */
class UploadTaskManager(
    private val context: Context,
    private val taskRepository: CallTaskRepository,
    private val config: ServiceConfig
) {
    private final val TAG = "UploadTaskManager"
    private val processingTaskIds = ConcurrentHashMap<Long, Boolean>()

    suspend fun handleUploadScheduling(): Boolean {
        return try {
            // 获取单个待上传任务
            val uploadTasks = taskRepository.getUploadPendingTasks(1)
            val firstTask = uploadTasks.firstOrNull()
            if (firstTask == null){
                Log.d(TAG, "数据库没有待上传文件，跳过")
                //更新上传状态
                EventAction.sendBroadcast(
                    ACTION_UPDATE_UPLOAD,
                    EXTRA_PHONE_NUMBER to "none",
                    EXTRA_STATUS to "空闲中",
                )
                false
            }
            firstTask?.let { task ->
                if (!processingTaskIds.getOrDefault(task.id, false)) {
                    processingTaskIds[task.id] = true
                    try {
                        uploadFileWithRetry(task)
                        true
                    } finally {
                        processingTaskIds.remove(task.id)
                    }
                } else {
                    Log.d(TAG, "任务 ${task.id} 正在处理中，跳过")
                    false
                }
            } ?: false
        } catch (e: AppException.DatabaseException) {
            Log.e(TAG, "数据库操作失败", e)
            false
        } catch (e: Exception) {
            Log.e(TAG, "上传调度失败", e)
            false
        }
    }

    /**
     * 上传文件 || 重试
     */
    private suspend fun uploadFileWithRetry(task: CallTask) {
        Log.d(TAG, "开始上传任务 ${task.id}")
        taskRepository.updateTaskStatus(task.id, CallTask.CallStatus.UPLOADING)
        //更新上传状态
        EventAction.sendBroadcast(
            ACTION_UPDATE_UPLOAD,
            EXTRA_PHONE_NUMBER to task.phoneNumber,
            EXTRA_STATUS to task.status.name,
        )

        var retryCount = task.uploadRetryCount
        var success = false

        while (retryCount < config.maxRetryCount && !success) {
            try {
                val serverPath = uploadFile(task)
                Log.d(TAG, "任务 ${task.id} 上传成功")
                task.status = CallTask.CallStatus.UPLOAD_SUCCESS

                //更新上传状态
                EventAction.sendBroadcast(
                    ACTION_UPDATE_UPLOAD,
                    EXTRA_PHONE_NUMBER to task.phoneNumber,
                    EXTRA_STATUS to task.status.name,
                )
                taskRepository.updateTaskStatusWithServerPath(task.id, CallTask.CallStatus.UPLOAD_SUCCESS, serverPath)
                success = true
            } catch (e: AppException.FileNotFoundException) {
                Log.e(TAG, "录音文件不存在", e)
                task.status = CallTask.CallStatus.UPLOAD_FAILED
                taskRepository.updateTaskStatusWithError(task.id, CallTask.CallStatus.UPLOAD_FAILED, "录音文件不存在")
                //更新上传状态
                EventAction.sendBroadcast(
                    ACTION_UPDATE_UPLOAD,
                    EXTRA_PHONE_NUMBER to "none",
                    EXTRA_STATUS to task.status.name,
                )
                break
            } catch (e: AppException.NetworkException){
                Log.e(TAG, "上传文件API调用失败", e)
                false
            } catch (e: AppException.TimeoutException){
                Log.e(TAG, "连接超时", e)
                false
            } catch (e: AppException.FileUploadException) {
                retryCount++
                Log.w(TAG, "任务 ${task.id} 第${retryCount}次上传失败")
                taskRepository.incrementUploadRetryCount(task.id)
                if (retryCount < config.maxRetryCount) {
                    delay(config.retryDelay.seconds)
                }
            }
        }

        if (!success) {
            Log.e(TAG, "任务 ${task.id} 上传最终失败")
            task.status = CallTask.CallStatus.UPLOAD_FAILED
            taskRepository.updateTaskStatusWithError(task.id, CallTask.CallStatus.UPLOAD_FAILED, "上传失败，重试${config.maxRetryCount}次后放弃")
            //更新上传状态
            EventAction.sendBroadcast(
                ACTION_UPDATE_UPLOAD,
                EXTRA_PHONE_NUMBER to task.phoneNumber,
                EXTRA_STATUS to task.status.name,
            )
        }
    }

    /**
     * 开始上传
     */
    private suspend fun uploadFile(task: CallTask): String {
        val localPath = task.localAudioPath
        // 检查文件是否存在
        if (localPath == null || localPath.isEmpty()){
            throw AppException.FileNotFoundException(localPath)
        }
        val wavFile = File(localPath)
        if (!wavFile.isFile){
            throw AppException.FileNotFoundException(localPath)
        }
        val params = hashMapOf<String,String>().apply {
            put("sysLoginName",AppConfig.userName)
            put("token",AppConfig.userToken)
            put("mobile",task.phoneNumber)
            put("orderId",task.orderId ?: "")
            put("userId",task.userId ?: "")
            put("product",task.product ?: "")
            put("mobileType",task.mobileType ?: "")
        }
        try {
            val data = HttpUtil.getInstance().uploadFileSuspend(context = context, url = HttpApi.API_UPLOAD_FILE, file = wavFile, fileParamName = "file", otherParams = params, headers = null)
            val code = data.optInt("code")
            if (code != 0){
                //通知Toast
                EventAction.sendBroadcast(
                    ACTION_UPDATE_TOAST,
                    EXTRA_STATUS to "error",
                    EXTRA_MESSAGE to "${data.optString("msg")}",
                )
                throw AppException.NetworkException(HttpApi.API_UPLOAD_FILE,code)
            }

            val dataObj = data.optJSONObject("obj")
            if (dataObj != null){
                return dataObj.optString("url","")
            }
            return ""
        } catch (e: Exception){
            throw AppException.TimeoutException(HttpApi.API_UPLOAD_FILE)
        }
    }
}